package com.hongfan.common.utils;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.HexUtil;

import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.HMac;
import cn.hutool.crypto.digest.HmacAlgorithm;
import cn.hutool.crypto.symmetric.AES;
import com.hongfan.common.utils.encrypt.Md5Utils;
import com.hongfan.common.utils.encrypt.RsaUtils;
import com.hongfan.common.utils.encrypt.SM4Utils;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

/**
 * 加解密辅助类
 *
 * @author yjr
 */
public class Crypto {

    private Crypto() {

    }

    /**
     * RSA解密
     *
     * @param content 解密内容
     * @return 解密结果
     */
    public static String decryptRsa(String content) {
        return RsaUtils.decrypt(content);
    }

    /**
     * RSA加密
     *
     * @param content 加密内容
     * @return 加密结果
     */
    public static String encryptRsa(String content) {
        return RsaUtils.encrypt(content);
    }

    /**
     * SHA256加密
     *
     * @param content 加密内容
     * @return 加密结果
     */
    public static String sha256(String content) {
        return SecureUtil.sha256(content);
    }

    /**
     * SHA256加密
     *
     * @param content 加密内容
     * @return 加密结果
     */
    public static String sha256(byte[] content) {
        return DigestUtil.sha256Hex(content);
    }

    /**
     * SHA256加密
     *
     * @param content 加密内容
     * @return 加密结果
     */
    public static String cSharpSha256(String content) {
        String encryptContent = Crypto.sha256(content);
        byte[] bytes = HexUtil.decodeHex(encryptContent);
        return cn.hutool.core.codec.Base64.encode(bytes);
    }

    /**
     * MD5加密，生成16进制MD5字符串<br>
     *
     * @param data 数据
     * @return MD5字符串
     */
    public static String md5(String data) {
        return Md5Utils.md5Encrypt(data).replace("-", "").toLowerCase();
    }

    /**
     * DES加密算法的密钥长度
     */
    private static final int DES_KEY_LENGTH = 8;

    /**
     * DES加密算法的向量长度
     */
    private static final int DES_IV_LENGTH = 8;

    /**
     * SM4加密
     *
     * @param content 加密内容
     * @return 加密结果
     */
    public static String sm4EcbEncrypt(String content) {
        SM4Utils utils = new SM4Utils();
        return utils.encryptDataECB(content);
    }

    /**
     * SM4加密
     *
     * @param content 加密内容
     * @return 加密结果
     */
    public static String sm4EcbEncrypt(String content, String key) {
        SM4Utils utils = new SM4Utils();
        utils.secretKey = key;
        return utils.encryptDataECB(content);
    }

    /**
     * SM4解密
     *
     * @param cipherText 密文
     * @return 明文
     */
    public static String sm4EcbDecrypt(String cipherText) {
        SM4Utils utils = new SM4Utils();
        return utils.decryptDataECB(cipherText);
    }

    /**
     * SM4解密
     *
     * @param cipherText 密文
     * @return 明文
     */
    public static String sm4EcbDecrypt(String cipherText, String key) {
        SM4Utils utils = new SM4Utils();
        utils.secretKey = key;
        return utils.decryptDataECB(cipherText);
    }

    /**
     * Base64解码
     *
     * @param str 编码后的内容
     * @return 解码后的内容
     */
    public static String base64Decode(String str) {
        byte[] bytes = cn.hutool.core.codec.Base64.decode(str);
        return new String(bytes, StandardCharsets.UTF_8);
    }

    /**
     * Base64解码
     *
     * @param str 编码后的内容
     * @return 解码后的内容
     */
    public static byte[] base64DecodeToByte(String str) {
        return cn.hutool.core.codec.Base64.decode(str);
    }

    /**
     * Base64编码
     *
     * @param bytes 要编码的数据
     * @return 编码后的内容
     */
    public static String base64Encode(byte[] bytes) {
        return cn.hutool.core.codec.Base64.encode(bytes);
    }

    /**
     * Base64编码
     *
     * @param content 明文
     * @return 编码后的内容
     */
    public static String base64Encode(String content) {
        return cn.hutool.core.codec.Base64.encode(content, StandardCharsets.UTF_8);
    }

    /**
     * AES加密
     *
     * <a href="https://the-x.cn/cryptography/Aes.aspx">测试站点</a>
     *
     * @param data    加密数据
     * @param mode    加密模式
     * @param padding 填充字符
     * @param key     密钥
     * @param iv      向量
     * @return 加密结果
     */
    public static String aesEncrypt(String data, Mode mode, Padding padding, String key, String iv) {
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(), "AES");
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
        AES aes = new AES(mode, padding, secretKeySpec, ivParameterSpec);
        return aes.encryptBase64(data, StandardCharsets.UTF_8);
    }

    /**
     * HMAC - SHA256
     *
     * @param data 待加密数据
     * @param key  密钥
     * @return 加密结果
     */
    public static String hmacSha256(String data, String key) {
        byte[] hmacKey = key.getBytes();
        HMac mac = new HMac(HmacAlgorithm.HmacSHA256, hmacKey);
        return mac.digestHex(data);
    }

    public static void main(String[] args) {
        // region 测试Base64
        String plainText = "中文测试";
        String result = "5Lit5paH5rWL6K+V";
        String value1 = Crypto.base64Encode(plainText);
        Assert.equals(value1, result);
        String value2 = Crypto.base64Decode(result);
        Assert.equals(value2, plainText);
        // endregion
    }

}
